Namespace.Use("Application.Sensor.Adapter.Distance", function(ns) {
    //
    //  Imports.
    //
    var DataSetConfiguration = Namespace.Import("Application.Sensor.DataSet.DataSetConfiguration");
    var Inherit = Namespace.Import("Base.Inherit");
    var BaseAdapter = Namespace.Import("Application.Sensor.Adapter.BaseAdapter");
    var QueryParameter = Namespace.Import("Application.Sensor.Query.QueryParameter");

    //
    //  Classes.
    //
    var DistanceLinearAdapter = Polymorphic.Create(
        [String, String, String, Number, Number, Number],
        function(name, color, device_id, route, min_distance, max_distance) {
            //  Let parent class initialize.
            BaseAdapter.call(this);

            //  Check the input.
            if (min_distance > max_distance) {
                throw "Invalid distance range.";
            }

            //
            //  Members.
            //
            var dataset = new DataSetConfiguration(name, color, min_distance, max_distance);
            var query = new QueryParameter(device_id, [route]);

            //
            //  Public methods.
            //
            this.ReceiveData = Polymorphic.Create(
                [String, Array, Array, Number],
                function(rcv_device_id, rcv_routes, rcv_values, rcv_timestamp) {
                    if (rcv_routes.length != rcv_values.length) {
                        throw "Corrupted data.";
                    }
                    if (rcv_device_id != device_id) {
                        return;
                    }
                    for (var idx = 0; idx < rcv_routes.length; ++idx) {
                        if (rcv_routes[idx] == route) {
                            this.TriggerDataCallback({
                                "Values": [
                                    min_distance + (rcv_values[idx] / 1024) * (max_distance - min_distance)
                                ],
                                "Time": rcv_timestamp
                            });
                            break;
                        }
                    }
                }
            );
            this.GetDataSets = function() {
                return [
                    dataset
                ];
            };
            this.GetQueryParameter = function() {
                return query;
            };
        }
    );

    //  Inherit "DistanceLinearAdapter" from "BaseAdapter".
    Inherit(DistanceLinearAdapter, BaseAdapter);

    var DistanceLinearAdapter2 = Polymorphic.Create(
        [String, String, String, Number, Number, Number, Number, Number, Number, Number],
        function(name, color, device_id, route, min_distance, max_distance, range_min, range_max, initial, constant_k) {
            //  Let parent class initialize.
            BaseAdapter.call(this);

            //  Check the input.
            if (min_distance > max_distance) {
                throw "Invalid distance range.";
            }

            //
            //  Members.
            //
            var dataset = new DataSetConfiguration(name, color, range_min, range_max);
            var query = new QueryParameter(device_id, [route]);

            //
            //  Public methods.
            //
            this.ReceiveData = Polymorphic.Create(
                [String, Array, Array, Number],
                function(rcv_device_id, rcv_routes, rcv_values, rcv_timestamp) {
                    if (rcv_routes.length != rcv_values.length) {
                        throw "Corrupted data.";
                    }
                    if (rcv_device_id != device_id) {
                        return;
                    }
                    for (var idx = 0; idx < rcv_routes.length; ++idx) {
                        if (rcv_routes[idx] == route) {
                            this.TriggerDataCallback({
                                "Values": [
                                    initial + (min_distance + (rcv_values[idx] / 1024) * (max_distance - min_distance)) * constant_k
                                ],
                                "Time": rcv_timestamp
                            });
                            break;
                        }
                    }
                }
            );
            this.GetDataSets = function() {
                return [
                    dataset
                ];
            };
            this.GetQueryParameter = function() {
                return query;
            };
        }
    );

    //  Inherit "DistanceLinearAdapter2" from "BaseAdapter".
    Inherit(DistanceLinearAdapter2, BaseAdapter);

 var DistanceLinearAdapter3 = Polymorphic.Create(
        [String, String, String, Number, Number, Number],
        function(name, color, device_id, route, min_distance, max_distance) {
            //  Let parent class initialize.
            BaseAdapter.call(this);

            //  Check the input.
            if (min_distance > max_distance) {
                throw "Invalid distance range.";
            }

            //
            //  Members.
            //
            var dataset = new DataSetConfiguration(name, color, min_distance, max_distance);
            var query = new QueryParameter(device_id, [route]);

            //
            //  Public methods.
            //
            this.ReceiveData = Polymorphic.Create(
                [String, Array, Array, Number],
                function(rcv_device_id, rcv_routes, rcv_values, rcv_timestamp) {
                    if (rcv_routes.length != rcv_values.length) {
                        throw "Corrupted data.";
                    }
                    if (rcv_device_id != device_id) {
                        return;
                    }
                    for (var idx = 0; idx < rcv_routes.length; ++idx) {
                        if (rcv_routes[idx] == route) {
                            this.TriggerDataCallback({
                                "Values": [
//                                    min_distance + (rcv_values[idx] / 1024) * (max_distance - min_distance)
                                        rcv_values[idx]
                                ],
                                "Time": rcv_timestamp
                            });
                            break;
                        }
                    }
                }
            );
            this.GetDataSets = function() {
                return [
                    dataset
                ];
            };
            this.GetQueryParameter = function() {
                return query;
            };
        }
    );

    //  Inherit "DistanceLinearAdapter" from "BaseAdapter".
    Inherit(DistanceLinearAdapter3, BaseAdapter);

    //  Export public APIs / classes.
    Namespace.Export(ns, "DistanceLinearAdapter", DistanceLinearAdapter);
    Namespace.Export(ns, "DistanceLinearAdapter2", DistanceLinearAdapter2);
    Namespace.Export(ns, "DistanceLinearAdapter3", DistanceLinearAdapter3);
});
